import face_recognition
import cv2
import os
import pymysql
import requests
from PIL import ImageFont, ImageDraw, Image
import numpy as np
import datetime
import time

DB = pymysql.connect(host='121.36.46.69', port=3306, user="root", password="zzyy0223", database="education",
                     charset='utf8')
CURSOR = DB.cursor()
IMG_SRC = 'https://' + input("请输入程序IP地址") + '/img/'
PATH = './data'
# 调用熟悉的人脸分类器
DETECTOR = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
FONT_PATH = "./simsun.ttc"  # <== 这里是宋体路径
FONT = ImageFont.truetype(FONT_PATH, 32)


def get_face_encodings(path):
    encodings = []
    image_paths = [os.path.join(path, f) for f in os.listdir(path)]
    names = []
    ids = []
    for image_path in image_paths:
        image = face_recognition.load_image_file(image_path)
        if os.path.split(image_path)[-1].split(".")[-1] != 'jpg':
            continue
        encoding = face_recognition.face_encodings(image)
        if encoding:
            encodings.append(encoding[0])
            names.append((os.path.split(image_path)[-1].split(".")[1]))
            ids.append((os.path.split(image_path)[-1].split(".")[2]))
    return encodings, names, ids


# 从接口获取图片
def get_img(path):
    # del_file(path)
    sql_st = "SELECT name,uid from account WHERE uid in (SELECT account from img_face where method = 0)"
    cursor = CURSOR
    cursor.execute(sql_st)
    img_list = list(cursor.fetchall())
    # image_paths = [os.path.join(path, f) for f in os.listdir(path)]
    for index in img_list:
        name = index[0]
        account_id = index[1]
        image_paths = [os.path.join(path, f) for f in os.listdir(path)]
        for image_path in image_paths:
            if str(account_id) in image_path:
                os.remove(image_path)
        img_request_path = IMG_SRC + '' + str(account_id)
        img = requests.get(img_request_path, verify=False).content
        with open(path + '/User.' + str(name) + '.' + str(account_id) + '.jpg', 'wb') as s:
            s.write(img)
        sql_st = "update img_face set method = 1 where account = '%s'" % account_id
        cursor.execute(sql_st)
        DB.commit()


def del_dir_file(path):
    ls = os.listdir(path)
    for i in ls:
        c_path = os.path.join(path, i)
        if os.path.isdir(c_path):
            del_dir_file(c_path)
        else:
            os.remove(c_path)


def mysql_update(account_id):
    cursor = CURSOR
    sql_st = "select date_time from img_face where account = '%s'" % (
        account_id)
    cursor.execute(sql_st)
    start_time = list(cursor.fetchall())[0][0]
    end_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    start_sec = time.mktime(time.strptime(start_time, '%Y-%m-%d %H:%M:%S'))
    end_sec = time.mktime(time.strptime(end_time, '%Y-%m-%d %H:%M:%S'))
    # 不是在很短时间内（2min内多次均为一次进出）或者一段时间以后的话，不允许进出
    print(end_sec - start_sec)
    if end_sec - start_sec > 600 or end_sec - start_sec < 150:
        # 如果是一段时间以后的话，在出入记录表中插入，并且在照片表中更新最近出入时间
        if end_sec - start_sec > 600:
            sql_st = "insert into record(date_time,method,student_uid) values ('%s','%s','%s')" % (
                datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 1, account_id)
            cursor.execute(sql_st)
            DB.commit()
            sql_st = "update img_face set date_time = '%s' where account = '%s'" % (
                datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), account_id)
            cursor.execute(sql_st)
            DB.commit()  # Display


def recognize(known_face_encodings, known_face_names, known_face_ids):
    video_capture = cv2.VideoCapture(0)
    face_locations = []
    face_names = []
    process_this_frame = True

    while True:
        # 读取摄像头画面
        ret, frame = video_capture.read()

        # 改变摄像头图像的大小，图像小，所做的计算就少
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)

        # opencv的图像是BGR格式的，而我们需要是的RGB格式的，因此需要进行一个转换。
        rgb_small_frame = small_frame[:, :, ::-1]

        # Only process every other frame of video to save time
        if process_this_frame:
            # 根据encoding来判断是不是同一个人，是就输出true，不是为flase
            face_locations = face_recognition.face_locations(rgb_small_frame)
            face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

            face_names = []
            for face_encoding in face_encodings:
                # 默认为unknown
                matches = face_recognition.compare_faces(known_face_encodings, face_encoding, tolerance=0.39)
                name = "Unknown"
                print(matches)
                # <class 'list'>
                # [True]

                # if match[0]:
                #     name = "michong"
                # If a match was found in known_face_encodings, just use the first one.
                if True in matches:
                    first_match_index = matches.index(True)
                    name = known_face_names[first_match_index]
                    account_id = known_face_ids[first_match_index]
                    mysql_update(account_id)
                face_names.append(name)
        process_this_frame = not process_this_frame
        # 将捕捉到的人脸显示出来
        for (top, right, bottom, left), name in zip(face_locations, face_names):
            # Scale back up face locations since the frame we detected in was scaled to 1/4 size
            top *= 4
            right *= 4
            bottom *= 4
            left *= 4
            # 矩形框
            cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
            img_pil = Image.fromarray(frame)
            draw = ImageDraw.Draw(img_pil)
            draw.text((left + 5, top - 50), str(name), font=FONT, fill=(0, 255, 0))
            frame = np.array(img_pil)
        cv2.imshow('monitor', frame)
        # 按Q退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    video_capture.release()
    cv2.destroyAllWindows()


if __name__ == '__main__':
    if os.path.exists(PATH):
        pass
    else:
        os.mkdir(PATH)
    # 从后端获取照片
    get_img(PATH)
    # 导入图像集
    e, n, i = get_face_encodings(PATH)
    recognize(e, n, i)
